package com.sl.gateway.filter;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.itheima.auth.sdk.dto.AuthUserInfoDTO;
import com.sl.gateway.config.MyConfig;
import com.sl.transport.common.constant.Constants;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * @author 姜星宇
 * @date 2024/9/3 20:26
 */

public class TokenGatewayFilter implements GatewayFilter, Ordered {


    private MyConfig myConfig;
    private AuthFilter authFilter;

    public TokenGatewayFilter(AuthFilter authFilter,MyConfig myConfig){
        this.authFilter = authFilter;
        this.myConfig = myConfig;
        }
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1. 校验请求路径，如果是白名单，直接放行
        String path = exchange.getRequest().getPath().toString();
        if (StrUtil.startWithAny(path,myConfig.getNoAuthPaths())) {
            //直接放行
            return chain.filter(exchange);
        }

        //2. 获取请求头中的token，进行校验，如果为空或校验失效，响应401
        String token = exchange.getRequest().getHeaders().getFirst(this.authFilter.tokenHeaderName());
        if (StrUtil.isEmpty(token)) {
            //设置响应状态为401
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            //拦截请求
            return exchange.getResponse().setComplete();
        }
        //校验token
        AuthUserInfoDTO authUserInfoDTO = null;
        try {
            authUserInfoDTO = this.authFilter.check(token);
        } catch (Exception e) {
            //token不可用，不做处理
        }

        if (ObjectUtil.isEmpty(authUserInfoDTO)) {
            //token不可用，设置响应状态为401
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            //拦截请求
            return exchange.getResponse().setComplete();
        }

        //3. 校验权限，如果是非管理员不能登录
        Boolean result = this.authFilter.auth(token, authUserInfoDTO, path);
        if (!result) {
            //无交集，说明没有权限，设置响应状态码为400
            exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
            return exchange.getResponse().setComplete();
        }
        //4. 校验通过，向下游传递用户信息和token
        exchange.getRequest().mutate().header(Constants.GATEWAY.USERINFO, JSONUtil.toJsonStr(authUserInfoDTO));
        exchange.getRequest().mutate().header(Constants.GATEWAY.TOKEN, token);
        //4.1 校验通过放行
        return chain.filter(exchange);
    };

    @Override
    public int getOrder() {
        return Integer.MIN_VALUE;
    }
}


